home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
strategy
/
colour-y.tgz
/
colour-y.tar
/
yahtzee
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-10-29
|
22KB
|
1,395 lines
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
#include <ncurses/ncurses.h>
#include <stdarg.h>
#include "yahtzee.h"
/*
* (c)1992 by orest zborowski
*/
static char *header = "Yahtzee Version 1.00 (c)1992 by zorst";
extern errno;
#define NUM_ROLLS 3
static char *upper_headers[NUM_UPPER] =
{
"(a) 1 [total of 1s]",
"(b) 2 [total of 2s]",
"(c) 3 [total of 3s]",
"(d) 4 [total of 4s]",
"(e) 5 [total of 5s]",
"(f) 6 [total of 6s]"
};
static char *lower_headers[NUM_LOWER] =
{
"(g) 3 of a Knd [total]",
"(h) 4 of a Knd [total]",
"(i) Full House [25]",
"(j) Sm Straight [30]",
"(k) Lg Straight [40]",
"(l) Yahtzee [50]",
"(m) Chance [total]",
};
int dice_values[5];
static char *dice[6][4] =
{
"",
" ",
" o ",
" ",
"",
"o ",
" ",
" o",
"",
"o ",
" o ",
" o",
"",
"o o",
" ",
"o o",
"",
"o o",
" o ",
"o o",
"",
"o o",
"o o",
"o o",
};
Player players[MAX_NUMBER_OF_PLAYERS];
int num_players;
static int longest_header;
int dodelay = 0;
int numlines;
init(void)
{
int i;
int j;
num_players = 0;
srand(getpid());
for (i = 0; i < MAX_NUMBER_OF_PLAYERS; ++i)
{
players[i].name[0] = '\0';
players[i].finished = 0;
players[i].comp = 0;
for (j = 0; j < NUM_FIELDS; ++j)
{
players[i].score[j] = 0;
players[i].used[j] = 0;
}
}
for (i = 0; i < NUM_UPPER; ++i)
if (strlen(upper_headers[i]) > longest_header)
longest_header = strlen(upper_headers[i]);
for (i = 0; i < NUM_LOWER; ++i)
if (strlen(lower_headers[i]) > longest_header)
longest_header = strlen(lower_headers[i]);
srand(getpid());
}
static void fill_box(int x,int y, int h, int w)
{
int dx,dy;
for(dy=y; dy<y+h; dy++)
{
for(dx=x;dx<x+w;dx++)
{
mvaddch(dx,dy,' ');
}
}
}
/*
** SCREEN ORGANIZATION:
** line 0: version header
** line 1: -----------
** line 2: edit window
** line 3: -----------
** line 4: player names
** line 5-10 upper bank
** line 11: upper total
** line 12: Bonus
** line 13-19: lower bank
** line 20: lower total
** line 21: total
*/
setup_screen(void)
{
int i;
initscr();
if (LINES < 23)
abort("Not enough lines on the terminal");
numlines = LINES;
if(has_colors())
{
start_color();
init_pair(COLOR_WHITE, COLOR_BLACK, COLOR_WHITE);
init_pair(COLOR_GREEN, COLOR_BLACK, COLOR_GREEN);
init_pair(COLOR_YELLOW, COLOR_WHITE, COLOR_GREEN);
init_pair(COLOR_RED, COLOR_WHITE, COLOR_RED);
}
clear();
wattron(stdscr, COLOR_PAIR(COLOR_GREEN));
fill_box(0,0,COLS,LINES);
mvaddstr(0, 9, header);
move(1, 9);
for (i = 9; i < COLS; ++i)
addch(ACS_HLINE);
refresh();
}
yend(void)
{
attron(0);
move(0, 0);
clear();
refresh();
endwin();
}
abort(char *msg)
{
yend();
putchar('\n');
printf(msg);
putchar('\n');
exit(1);
}
say(char *fmt, ...)
{
va_list ap;
char buf[200];
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
va_end(ap);
fill_box(2,10,COLS-10,1);
mvaddstr(2, 10, buf);
refresh();
}
/*
** we have a trick in here - we will accept a '?' as the first character of
** a human answer. in that case, we ask the computer for the die to roll
** or the place to put it. then the human can decide what to do.
*/
void
query(int player, int question, char *prompt, char *ans, int len)
{
int i;
char c;
int xpos;
char foo[2];
xpos = 10 + strlen(prompt);
if (player >= 0 && players[player].comp) /* for the computer */
{
fill_box(2,10,COLS-10,1);
mvaddstr(2, 10, prompt);
be_computer(player, question, ans, len);
mvaddstr(2, xpos, ans);
refresh();
if (dodelay)
sleep(COMPUTER_DELAY); /* let person read it */
return;
}
for (;;)
{
cbreak();
noecho();
fill_box(2,10,COLS-10,1);
mvaddstr(2, 10, prompt);
refresh();
i = 0;
for (;;)
{
c = getch();
if (c == '\b' || c == 0x7f)
{
if (i == 0)
continue;
--i;
--xpos;
mvaddch(2, xpos, ' ');
move(2, xpos);
}
else if (c == 10 || c == 13)
break;
else
{
if (i == len)
write(1, "\007", 1);
else
{
addch(c);
ans[i] = c;
++xpos;
++i;
}
}
refresh();
}
ans[i] = '\0';
echo();
nocbreak();
if (ans[0] != '?')
break;
/*
** let the computer decide and then we can put that up for the human to
** read
*/
be_computer(player, question, ans, len);
query(-1, 0, ans, foo, sizeof(foo));
}
}
int
raw_roll_dice(void)
{
return((rand() % 6) + 1);
}
int
roll_dice(int num)
{
int val;
int i;
int j;
if (num < 1 || num > 5)
abort("Bad dice loc passed");
attron(COLOR_PAIR(COLOR_GREEN));
for (j = 0; j < 1; ++j)
{
/*
val = (random() % 6) + 1;
*/
val = raw_roll_dice();
for (i = 0; i < 4; ++i)
{
move(((num - 1) * 4) + i, 0);
if (i == 2)
printw("%d", num);
else
addch(' ');
attroff(COLOR_PAIR(COLOR_GREEN));
attron(COLOR_PAIR(COLOR_WHITE));
if(i==0)
{
if(num==1)
addch(ACS_ULCORNER);
else
addch(ACS_LTEE);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
if(num==1)
addch(ACS_URCORNER);
else
addch(ACS_RTEE);
}
else
{
addch(ACS_VLINE);
addstr(dice[val - 1][i]);
addch(ACS_VLINE);
}
attroff(COLOR_PAIR(COLOR_WHITE));
attron(COLOR_PAIR(COLOR_GREEN));
}
if (num == 5) /* put the last +---+ tail */
{
mvaddch(20, 0, ' ');
attroff(COLOR_PAIR(COLOR_GREEN));
attron(COLOR_PAIR(COLOR_WHITE));
addch(ACS_LLCORNER);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_HLINE);
addch(ACS_LRCORNER);
attroff(COLOR_PAIR(COLOR_WHITE));
attron(COLOR_PAIR(COLOR_GREEN));
}
}
refresh();
return (val);
}
int
upper_total(int num)
{
int val;
int i;
val = 0;
for (i = 0; i < NUM_UPPER; ++i)
val += players[num].score[i];
return (val);
}
int
lower_total(int num)
{
int val;
int i;
val = 0;
for (i = 0; i < NUM_LOWER; ++i)
val += players[num].score[i + NUM_UPPER];
return (val);
}
int
total_score(int num)
{
int upper_tot;
int lower_tot;
int i;
upper_tot = 0;
lower_tot = 0;
lower_tot = lower_total(num);
upper_tot = upper_total(num);
if (upper_tot >= 63)
upper_tot += 35;
return (upper_tot + lower_tot);
}
void
show_player(int num, int field)
{
int i;
int line;
int upper_tot;
int lower_tot;
int xpos;
xpos = 10 + longest_header + (num * MAX_NAME_LENGTH);
for (i = 0; i < NUM_FIELDS; ++i)
{
if (i == field || field == -1)
{
line = 5 + i;
if (i >= NUM_UPPER)
line += 2;
move(line, xpos);
if (players[num].used[i])
printw(" %4d", players[num].score[i]);
else
addstr(" ");
}
}
upper_tot = upper_total(num);
lower_tot = lower_total(num);
move(12, xpos);
if (upper_tot >= 63)
{
printw("+%4d", 35);
upper_tot += 35;
}
else
addstr(" ");
mvprintw(11, xpos, "(%4d)", upper_tot);
mvprintw(20, xpos, "(%4d)", lower_tot);
mvprintw(21, xpos, "[%4d]", upper_tot + lower_tot);
refresh();
}
void
setup_board(void)
{
int i;
int j;
move(3, 9);
for (i = 9; i < COLS; ++i)
addch(ACS_HLINE);
for (i = 0; i < NUM_UPPER; ++i)
mvaddstr(i+5, 9, upper_headers[i]);
move(11, 9);
attron(A_UNDERLINE|COLOR_PAIR(COLOR_YELLOW));
addstr(" Upper Total");
move(12, 9);
addstr(" Bonus");
attroff(A_UNDERLINE|COLOR_PAIR(COLOR_YELLOW));
attron(COLOR_PAIR(COLOR_GREEN));
for (i = 0; i < NUM_LOWER; ++i)
mvaddstr(i+13, 9, lower_headers[i]);
move(20, 9);
attron(A_UNDERLINE|COLOR_PAIR(COLOR_YELLOW));
addstr(" Lower Total");
move(21, 9);
addstr(" Grand Total");
attroff(A_UNDERLINE|COLOR_PAIR(COLOR_YELLOW));
attron(COLOR_PAIR(COLOR_GREEN));
for (j = 0; j < num_players; ++j)
{
for (i = 4; i < 22; ++i)
mvaddch(i, 9 + longest_header + (j * MAX_NAME_LENGTH),
ACS_VLINE);
}
for (i = 0; i < num_players; ++i)
{
mvaddstr(4, 10 + longest_header + (i * MAX_NAME_LENGTH),
players[i].name);
show_player(i, -1);
}
refresh();
}
int
count(int val)
{
int i;
int num;
num = 0;
for (i = 0; i < 5; ++i)
if (dice_values[i] == val)
++num;
return (num);
}
int
find_n_of_a_kind(int n, int but_not)
{
int val;
int i;
int j;
for (i = 0; i < 5; ++i)
{
if (dice_values[i] == but_not)
continue;
if (count(dice_values[i]) >= n)
return (dice_values[i]);
}
return (0);
}
int
find_straight(int run, int notstart, int notrun)
{
int i;
int j;
for (i = 1; i < 7; ++i)
{
if (i >= notstart && i < notstart + notrun)
continue;
for (j = 0; j < run; ++j)
if (!count(i + j))
break;
if (j == run)
return (i);
}
return (0);
}
int
find_yahtzee(void)
{
int i;
for (i = 1; i < 7; ++i)
if (count(i) == 5)
return (i);
return (0);
}
int
add_dice(void)
{
int i;
int val;
val = 0;
for (i = 0; i < 5; ++i)
val += dice_values[i];
return (val);
}
int
showoff(int p, short so)
{
move(4, 10 + longest_header + (p * MAX_NAME_LENGTH));
if (so)
{
attroff(COLOR_PAIR(COLOR_GREEN));
attron(A_STANDOUT);
}
else
attron(COLOR_PAIR(COLOR_GREEN));
addstr(players[p].name);
if (so)
{
attroff(A_STANDOUT);
attron(COLOR_PAIR(COLOR_GREEN));
}
refresh();
}
void
handle_play(int player)
{
int i;
char buf[50];
char *cp;
char *num;
int done;
int field;
int dummy;
int numroll;
if (players[player].finished) /* all finished */
return;
showoff(player, 1);
say("Rolling for %s", players[player].name);
for (i = 1; i < 6; ++i)
dice_values[i - 1] = roll_dice(i);
for (numroll = 1; numroll < NUM_ROLLS; ++numroll)
{
query(player, 1, "What dice to roll again (<RETURN> for none)? ",
buf, sizeof(buf));
cp = buf;
if (*cp == '\0')
break;
done = 0;
for (;;)
{
num = cp;
while (*cp != '\0' && *cp != ',' && *cp != '\t' && *cp != ' ')
++cp;
if (*cp == '\0')
done = 1;
*cp++ = '\0';
i = atoi(num);
if (i >= 1 && i <= 5)
dice_values[i - 1] = roll_dice(i);
if (done)
break;
}
}
query(player, 2, "Where do you want to put that? ", buf, sizeof(buf));
done = 0;
for (;;)
{
if (buf[0] < 'a' || buf[0] > 'm')
{
query(player, 2, "No good! Where do you want to put that? ",
buf, sizeof(buf));
continue;
}
field = buf[0] - 'a';
switch(field)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
players[player].score[field] =
count(field + 1) * (field + 1);
done = 1;
show_player(player, field);
break;
case 6:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
if (find_n_of_a_kind(3, 0))
players[player].score[field] =
add_dice();
show_player(player, field);
done = 1;
break;
case 7:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
if (find_n_of_a_kind(4, 0))
players[player].score[field] =
add_dice();
show_player(player, field);
done = 1;
break;
case 8:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
dummy = find_n_of_a_kind(3, 0);
if (dummy != 0)
{
if (find_n_of_a_kind(2, dummy))
players[player].score[field] =
25;
}
show_player(player, field);
done = 1;
break;
case 9:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
if (find_straight(4, 0, 0))
players[player].score[field] = 30;
show_player(player, field);
done = 1;
break;
case 10:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
if (find_straight(5, 0, 0))
players[player].score[field] = 40;
show_player(player, field);
done = 1;
break;
case 11:
/*
** if the player scratched, the score for that field will be 0.
** in that case, we don't allow it to be used any more.
*/
if ((players[player].score[field] == 0 ||
!find_yahtzee()) &&
players[player].used[field] == 1)
{
query(player, 2, "Already used! (he he) Where do you want to put that? ",
buf, sizeof(buf));
break;
}
if (find_yahtzee())
players[player].score[field] += 50;
players[player].used[field] = 1;
show_player(player, field);
done = 1;
break;
case 12:
if (players[player].used[field])
{
query(player, 2, "Already used! Where do you want to put that? ",
buf, sizeof(buf));
break;
}
players[player].used[field] = 1;
players[player].score[field] = add_dice();
show_player(player, field);
done = 1;
break;
}
if (done)
break;
}
showoff(player, 0);
for (i = 0; i < NUM_FIELDS; ++i)
if (!players[player].used[i])
return;
players[player].finished = 1;
}
void
play(void)
{
int i;
int topscore;
int winner;
for (;;)
{
for (i = 0; i < num_players; ++i)
handle_play(i);
for (i = 0; i < num_players; ++i)
if (!players[i].finished)
break;
if (i == num_players)
break;
}
topscore = -1;
for (i = 0; i < num_players; ++i)
if (total_score(i) > topscore)
{
topscore = total_score(i);
winner = i;
}
say("The winner is %s", players[winner].name);
}
#define L_LOCK 0
#define L_UNLOCK 1
void
lock(char *fname, int type)
{
char lockfile[200];
struct stat statbuf;
int i;
FILE *fp;
strcpy(lockfile, fname);
strcat(lockfile, ".L");
if (type == L_LOCK)
{
for (i = 1; ;++i)
{
stat(lockfile, &statbuf);
if (errno == ENOENT)
break;
say("Waiting for lock... (%d)", i);
sleep(1);
}
fp = fopen(lockfile, "w");
fclose(fp);
}
else
{
unlink(lockfile);
}
}
static int
write_score(FILE *fp, char *name, char *date, int score)
{
return fprintf(fp, "%s\001%s\001%d\n", name, date, score);
}
static int
read_score(FILE *fp, char *name, char *date, int *score)
{
char buf[200];
char *sb, *se;
if (!fgets(buf, sizeof(buf), fp))
return -1;
if (!(se = strchr(buf, '\001')))
return -1;
*se++ = '\0';
strcpy(name, buf);
if ((sb = se) > buf + sizeof(buf))
return -1;
if (!(se = strchr(sb, '\001')))
return -1;
*se++ = '\0';
strcpy(date, sb);
if ((sb = se) > buf + sizeof(buf))
return -1;
if (!(se = strchr(sb, '\n')))
return -1;
*se = '\0';
*score = atoi(sb);
return 0;
}
/*
** we keep track of the top nnn persons.
*/
void
update_scorefile(void)
{
FILE *fp;
FILE *tp;
char scorefile[200];
char tmpfile[100];
int numtop;
int nump;
int j;
char name[20];
char date[30];
char *curdate;
int score;
int topscore;
int tmptop;
long clock;
char scall[100];
sprintf(tmpfile, "%s/y.%x", SCOREDIR, getpid());
sprintf(scorefile, "%s/%s", SCOREDIR, SCOREFNAME);
clock = time(0);
curdate = (char *) ctime(&clock);
if (strchr(curdate, '\n'))
*strchr(curdate, '\n') = '\0';
if ((tp = fopen(tmpfile, "w")) == NULL)
{
say("Can't update score file.");
return;
}
lock(scorefile, L_LOCK);
fp = fopen(scorefile, "r");
for (j = 0; j < num_players; ++j)
players[j].finished = -1;
numtop = 0;
nump = 0;
topscore = 99999;
for (;;)
{
/*
** get the next entry from the score file. if there isn't any, then
** we set the score to beat to -99 (everyone playing can beat it)
*/
if (fp == NULL || read_score(fp, name, date, &score))
score = -99;
/*
** now, we search through all players to find out which ones have scores
** higher than the one read (but less than topscore). these will get
** saved before the read entry does. now, we only do this if all players
** haven't been accounted for.
*/
for (; nump != num_players;)
{
tmptop = -99;
for (j = 0; j < num_players; ++j)
if (total_score(j) > tmptop &&
total_score(j) < topscore)
{
tmptop = total_score(j);
}
if (tmptop == -99) /* everybody better */
break;
if (tmptop > score)
{
topscore = tmptop;
for (j = 0; j < num_players; ++j)
if (total_score(j) == tmptop)
{
if (numtop >= NUM_TOP_PLAYERS)
break;
write_score(tp,
players[j].name, curdate,
tmptop);
players[j].finished = numtop;
++nump;
++numtop;
}
}
else
break;
}
if (score != -99 && numtop < NUM_TOP_PLAYERS)
{
write_score(tp, name, date, score);
++numtop;
}
/*
** if we processed all top slots or processed all players (and there
** was no score to beat), we stop.
*/
if (numtop == NUM_TOP_PLAYERS ||
(nump == num_players && score == -99))
break;
}
fclose(tp);
if (fp)
fclose(fp);
#ifdef HAS_RENAME
if (rename(tmpfile, scorefile))
{
say("rename failed!");
unlink(tmpfile);
}
#else
sprintf(scall, "mv %s %s", tmpfile, scorefile);
system(scall);
#endif
lock(scorefile, L_UNLOCK);
}
void
show_top_scores(void)
{
FILE *fp;
char scorefile[200];
int i, j, k, score;
char stuff[1024];
char name[32], date[32];
attron(COLOR_PAIR(COLOR_RED));
fill_box(0,0,COLS,LINES);
attroff(COLOR_PAIR(COLOR_RED));
attron(COLOR_PAIR(COLOR_WHITE));
fill_box(0,0,COLS,1);
move(0,(COLS-strlen("Yahtzee Top Scores"))/2);
addstr("Yahtzee Top Scores");
attroff(COLOR_PAIR(COLOR_WHITE));
sprintf(scorefile, "%s/%s", SCOREDIR, SCOREFNAME);
if ((fp = fopen(scorefile, "r")) == NULL)
{
yend();
printf("Can't get at score file.\n");
return;
}
j = 0;
attron(COLOR_PAIR(COLOR_RED));
for (i = 0; i < NUM_TOP_PLAYERS; ++i)
{
if (read_score(fp, name, date, &score))
break;
if (j >= numlines - 4)
{
move(23,(COLS-strlen("<Hit Return>"))/2);
addstr("<Hit Return>");
refresh();
getch();
j = 0;
}
for (k = 0; k < num_players; ++k)
if (players[k].finished == i)
break;
fill_box(j+3,4,COLS-4,1);
move(j+3,4);
sprintf(stuff,"%3d : %-10s %s %d", i + 1, name, date, score);
addstr(stuff);
++j;
}
fclose(fp);
move(23,(COLS-strlen("<Hit Return>"))/2);
addstr("<Hit Return>");
refresh();
getch();
yend();
}
void
calc_random(void)
{
char nrollstr[10];
int nroll;
int table[NUM_FIELDS];
int i;
int j;
printf ("How many times to you wish to roll? ");
gets(nrollstr);
nroll = atoi(nrollstr);
printf("Generating...\n");
for (i = 0; i < NUM_FIELDS; ++i)
table[i] = 0;
for (i = 0; i < nroll; ++i)
{
for (j = 0; j < 5; ++j)
dice_values[j] = raw_roll_dice();
for (j = 1; j <= 6; ++j)
if (count(j) > 0)
++table[j-1];
if (find_n_of_a_kind(3, 0))
++table[6];
if (find_n_of_a_kind(4, 0))
++table[7];
j = find_n_of_a_kind(3, 0);
if (j != 0 && find_n_of_a_kind(2, j))
++table[8];
if (find_straight(4, 0, 0))
++table[9];
if (find_straight(5, 0, 0))
++table[10];
if (find_yahtzee())
++table[11];
}
printf("%-35s %10s %20s\n", "Results:", "Num Rolls", "Total");
for (i = 0; i < NUM_FIELDS; ++i)
{
if (i < NUM_UPPER)
printf("%-35s", upper_headers[i]);
else
printf("%-35s", lower_headers[i-NUM_UPPER]);
printf(" %10d %20d\n", table[i],
(long) (table[i] * 100) / nroll);
}
}
void
signal_trap()
{
yend();
exit(0);
}
set_signal_traps()
{
signal(SIGHUP, signal_trap);
signal(SIGINT, signal_trap);
signal(SIGQUIT, signal_trap);
}
main(int argc, char **argv)
{
char num[10];
int i;
int num_computers;
short onlyshowscores = 0;
while (--argc > 0)
{
if ((*++argv)[0] == '-')
{
switch ((*argv)[1])
{
case 's':
onlyshowscores = 1;
break;
case 'n':
printf("obsolete function - delay turned off by default.\n");
break;
case 'd':
dodelay = 1;
break;
case 'r':
calc_random();
exit(0);
default:
printf("usage: yahtzee [-s] [-d] [-r]\n");
printf("\t-s\tonly show scores\n");
printf("\t-d\tcomputer move delay\n");
printf("\t-r\tcalculate random die throws (debug)\n");
exit(0);
}
}
}
if (!onlyshowscores)
{
printf("\n\nWelcome to the game of Yahtzee...\n\n");
init();
do
{
printf("How many wish to play (max of %d)? ",
MAX_NUMBER_OF_PLAYERS);
fflush(stdout);
fgets(num, 10, stdin);
if (strchr(num, '\n'))
*strchr(num, '\n') = '\0';
num_players = atoi(num);
if (num_players == 0)
break;
}
while (num_players < 1 || num_players > MAX_NUMBER_OF_PLAYERS);
for (i = 0; i < num_players; ++i)
{
printf("What is the name of player #%d ? ", i + 1);
fflush(stdout);
fgets(players[i].name, MAX_NAME_LENGTH, stdin);
if (strchr(players[i].name, '\n'))
*strchr(players[i].name, '\n') = '\0';
}
if (num_players == MAX_NUMBER_OF_PLAYERS)
{
printf("Boo hoo... I can't play...\n");
}
else
{
do
{
printf("How many computers to play (max of %d) ? ",
MAX_NUMBER_OF_PLAYERS - num_players);
fflush(stdout);
fgets(num, sizeof(num), stdin);
num_computers = atoi(num);
}
while (num_computers < 0 ||
num_players + num_computers > MAX_NUMBER_OF_PLAYERS);
for (i = 0; i < num_computers; ++i)
{
players[num_players].comp = 1;
sprintf(players[num_players].name, "Mr. %c",
i + 'A');
++num_players;
}
}
if (num_players == 0)
{
printf("Well, why did you run this anyways???\n\n");
exit(8);
}
}
setup_screen();
set_signal_traps();
if (!onlyshowscores)
{
setup_board();
play();
update_scorefile();
}
getch();
show_top_scores();
exit(0);
}